package com.huihang.core.utils;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;

public class EncryptUtils {
    private static final String AES_MODE = "AES/GCM/NoPadding";
    private static final int GCM_TAG_LENGTH = 128;
    private static final int AES_KEY_SIZE = 32; // 32字节 = 256位密钥
    private static final int GCM_IV_SIZE = 12;  // GCM模式下通常使用12字节IV

    // 定义固定的密钥和IV
    private static final byte[] FIXED_KEY = new byte[]{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA,  (byte) 0xBB, (byte)0xCC, (byte)0xDD, (byte)0xEE, (byte)0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte)0x88,(byte) 0x99, (byte)0xAA, (byte)0xBB,(byte) 0xCC, (byte)0xDD, (byte)0xEE,(byte) 0xFF};

    private static final byte[] FIXED_IV = new byte[]{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B};

    private static final SecretKey key = new SecretKeySpec(FIXED_KEY, "AES");
    private static final byte[] iv = FIXED_IV;

    /**
     * 使用提供的 AES 密钥和初始化向量（IV）对数据进行加密。
     *
     * @param data 要加密的数据
     * @return 返回 Base64 编码的加密结果
     */
    public static String aesEncrypt(String data) {
        try {
            Cipher cipher = Cipher.getInstance(AES_MODE);
            GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
            cipher.init(Cipher.ENCRYPT_MODE, key, spec);
            byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(encrypted);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用提供的 AES 密钥和初始化向量（IV）对加密的数据进行解密。
     *
     * @param encryptedData Base64 编码的加密数据
     * @return 返回解密后的原始数据
     */
    public static String aesDecrypt(String encryptedData) {
        try {
            Cipher cipher = Cipher.getInstance(AES_MODE);
            GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
            cipher.init(Cipher.DECRYPT_MODE, key, spec);
            byte[] decoded = Base64.getDecoder().decode(encryptedData);
            byte[] decrypted = cipher.doFinal(decoded);
            return new String(decrypted, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 生成一个指定长度的随机密钥。
     *
     * @return 生成的AES密钥
     */
    private static SecretKey generateAESKey() {
        byte[] keyBytes = new byte[AES_KEY_SIZE];
        SecureRandom random = new SecureRandom();
        random.nextBytes(keyBytes);
        return new SecretKeySpec(keyBytes, "AES");
    }

    /**
     * 生成一个指定长度的随机IV。
     *
     * @return 生成的IV字节数组
     */
    private static byte[] generateIV() {
        byte[] iv = new byte[GCM_IV_SIZE];
        SecureRandom random = new SecureRandom();
        random.nextBytes(iv);
        return iv;
    }
    /**
     * 对输入字符串进行 MD5 哈希计算。
     *
     * @param data 要哈希的字符串
     * @return 返回 32 位十六进制表示的 MD5 哈希值
     * @throws NoSuchAlgorithmException 如果无法获取指定算法的消息摘要实例
     */
    public static String md5(String data){
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        byte[] digest = md.digest(data.getBytes(StandardCharsets.UTF_8));
        return bytesToHex(digest);
    }

    /**
     * 对输入字符串进行 SHA-256 哈希计算。
     *
     * @param data 要哈希的字符串
     * @return 返回 64 位十六进制表示的 SHA-256 哈希值
     * @throws NoSuchAlgorithmException 如果无法获取指定算法的消息摘要实例
     */
    public static String sha256(String data) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] digest = md.digest(data.getBytes(StandardCharsets.UTF_8));
        return bytesToHex(digest);
    }

    /**
     * 使用提供的 AES 密钥和初始化向量（IV）对数据进行加密。
     *
     * @param data 要加密的数据
     * @param key  AES 加密密钥
     * @param iv   初始化向量，对于 GCM 模式应为 12 字节
     * @return 返回 Base64 编码的加密结果
     * @throws Exception 如果加密过程中出现错误
     */
    public static String aesEncrypt(String data, SecretKey key, byte[] iv) {

        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance(AES_MODE);
            GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
            cipher.init(Cipher.ENCRYPT_MODE, key, spec);
            byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(encrypted);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用提供的 AES 密钥和初始化向量（IV）对加密的数据进行解密。
     *
     * @param encryptedData Base64 编码的加密数据
     * @param key           AES 解密密钥
     * @param iv            初始化向量，对于 GCM 模式应为 12 字节
     * @return 返回解密后的原始数据
     * @throws Exception 如果解密过程中出现错误
     */
    public static String aesDecrypt(String encryptedData, SecretKey key, byte[] iv)  {
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance(AES_MODE);
            GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
            cipher.init(Cipher.DECRYPT_MODE, key, spec);
            byte[] decoded = Base64.getDecoder().decode(encryptedData);
            byte[] decrypted = cipher.doFinal(decoded);
            return new String(decrypted, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }




    /**
     * 使用 RSA 公钥对数据进行加密。
     *
     * @param data      要加密的数据
     * @param publicKey RSA 公钥
     * @return 返回 Base64 编码的加密结果
     * @throws Exception 如果加密过程中出现错误
     */
    public static String rsaEncrypt(String data, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    /**
     * 使用 RSA 私钥对加密的数据进行解密。
     *
     * @param encryptedData Base64 编码的加密数据
     * @param privateKey    RSA 私钥
     * @return 返回解密后的原始数据
     * @throws Exception 如果解密过程中出现错误
     */
    public static String rsaDecrypt(String encryptedData, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decoded = Base64.getDecoder().decode(encryptedData);
        byte[] decrypted = cipher.doFinal(decoded);
        return new String(decrypted, StandardCharsets.UTF_8);
    }


    /**
     * 生成一个指定大小的 RSA 密钥对。
     *
     * @param keySize RSA 密钥长度（例如 2048）
     * @return 返回生成的 KeyPair 对象，包含公钥和私钥
     * @throws NoSuchAlgorithmException 如果无法获取指定算法的密钥对生成器实例
     */
    public static KeyPair generateRsaKeyPair(int keySize) throws NoSuchAlgorithmException {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(keySize);
        return keyGen.generateKeyPair();
    }

    /**
     * 生成一个新的 AES 密钥。
     *
     * @return 返回生成的 AES SecretKey 对象
     * @throws NoSuchAlgorithmException 如果无法获取指定算法的密钥生成器实例
     */
    public static SecretKey generateAesKey() throws NoSuchAlgorithmException {
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(AES_KEY_SIZE);
        return keyGen.generateKey();
    }

    /**
     * 将字节数组转换为十六进制字符串。
     *
     * @param bytes 要转换的字节数组
     * @return 返回对应的十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}